<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Widgets II in PyGTK</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, PyGTK, Widgets, Python, programming, Linux">
<meta name="description" content="Widgets II in PyGTK">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div> 

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Widgets II in PyGTK</h1>

<p>
In this part of the PyGTK programming tutorial, we continue 
introducing PyGTK widgets.
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script>


<h2>Entry</h2>

<p>
The <b class="keyword">Entry</b> is a single line text entry field. 
This widget is used to enter textual data. 
</p>

<div class="codehead">entry.py</div> 
<pre class="code">
#!/usr/bin/python

# ZetCode PyGTK tutorial 
#
# This example demonstrates the Entry widget
#
# author: jan bodnar
# website: zetcode.com 
# last edited: February 2009

import gtk

class PyApp(gtk.Window):

    def __init__(self):
        super(PyApp, self).__init__()
        
        self.set_title("Entry")
        self.set_size_request(250, 200)
        self.set_position(gtk.WIN_POS_CENTER)

        fixed = gtk.Fixed()

        self.label = gtk.Label("...")
        fixed.put(self.label, 60, 40)

        entry = gtk.Entry()
        entry.add_events(gtk.gdk.KEY_RELEASE_MASK)
        fixed.put(entry, 60, 100)

        entry.connect("key-release-event", self.on_key_release)

        self.connect("destroy", gtk.main_quit)
        self.add(fixed)
        self.show_all()

    def on_key_release(self, widget, event):
        self.label.set_text(widget.get_text())
        
PyApp()
gtk.main()
</pre>

<p>
This example shows an entry widget and a label. The text that we key in the 
entry is displayed immediately in the label control. 
</p>

<pre class="explanation">
 entry = gtk.Entry()
</pre>

<p>
<b class="keyword">Entry</b> widget is created. 
</p>

<pre class="explanation">
 entry.connect("key-release-event", self.on_key_release)
</pre>

<p>
If the text in the <b class="keyword">Entry</b> widget is changed,
we call the <b class="keyword">on_key_release()</b> method.
</p>

<pre class="explanation">
 def on_key_release(self, widget, event):
     self.label.set_text(widget.get_text())
</pre>

<p>
We get the text from the <b class="keyword">Entry</b> widget and
set it to the label. 
</p>


<br>
<img src="/img/gui/pygtk/entry.png" alt="Entry Widget">
<div class="figure">Figure: Entry Widget</div>
<br>


<h2>HScale</h2>

<p>
The <b class="keyword">HScale</b> is It is a horizontal slider,
that lets the user graphically select a value 
by sliding a knob within a bounded interval. 
Our example will show a volume control. 
</p>

<div class="codehead">hscale.py</div> 
<pre class="code">
#!/usr/bin/python

# ZetCode PyGTK tutorial 
#
# This example demonstrates the HScale widget
#
# author: jan bodnar
# website: zetcode.com 
# last edited: February 2009


import gtk
import sys


class PyApp(gtk.Window):

    def __init__(self):
        super(PyApp, self).__init__()

        self.set_title("Scale")
        self.set_size_request(260, 150)
        self.set_position(gtk.WIN_POS_CENTER)

        scale = gtk.HScale()
        scale.set_range(0, 100)
        scale.set_increments(1, 10)
        scale.set_digits(0)
        scale.set_size_request(160, 35)
        scale.connect("value-changed", self.on_changed)

        self.load_pixbufs()
        
        self.image = gtk.Image()
        self.image.set_from_pixbuf(self.mutp)

        fix = gtk.Fixed()
        fix.put(scale, 20, 40)
        fix.put(self.image, 219, 50)

        self.add(fix)

        self.connect("destroy", lambda w: gtk.main_quit())
        self.show_all()
        
    def load_pixbufs(self):
    
        try:
            self.mutp = gtk.gdk.pixbuf_new_from_file("mute.png")
            self.minp = gtk.gdk.pixbuf_new_from_file("min.png")
            self.medp = gtk.gdk.pixbuf_new_from_file("med.png")
            self.maxp = gtk.gdk.pixbuf_new_from_file("max.png")
            
        except Exception, e: 
            print "Error reading Pixbufs"
            print e.message
            sys.exit(1)


    def on_changed(self, widget):
        val = widget.get_value()

        if val == 0:
            self.image.set_from_pixbuf(self.mutp)
        elif val > 0 and val <= 30:
            self.image.set_from_pixbuf(self.minp)
        elif val > 30 and val < 80:
            self.image.set_from_pixbuf(self.medp)
        else: 
            self.image.set_from_pixbuf(self.maxp)
                 
        

PyApp()
gtk.main()
</pre>

<p>
In the example above, we have  <b class="keyword">HScale</b> and 
<b class="keyword">Image</b> widgets. By dragging the scale we change the image
on the <b class="keyword">Image</b> widget.
</p>

<pre class="explanation">
 scale = gtk.HScale()
</pre>

<p>
<b class="keyword">HScale</b> widget is created.
</p>

<pre class="explanation">
 scale.set_range(0, 100)
</pre>

<p>
We set the lower and upper boundaries of the scale. 
</p>

<pre class="explanation">
 scale.set_increments(1, 10)
</pre>

<p>
The <b class="keyword">set_increments()</b> method sets the step and page sizes for the range.
</p>

<pre class="explanation">
 scale.set_digits(0)
</pre>

<p>
We want to have integer values on the scale, so we set the number
of decimal places to zero.
</p>


<pre class="explanation">
 if val == 0:
     self.image.set_from_pixbuf(self.mutp)
 elif val > 0 and val <= 30:
     self.image.set_from_pixbuf(self.minp)
 elif val > 30 and val < 80:
     self.image.set_from_pixbuf(self.medp)
 else: 
     self.image.set_from_pixbuf(self.maxp)
</pre>

<p>
Depending on the obtained value, we change the picture in
the image widget. 
</p>

<br>
<img src="/img/gui/pygtk/scale.png" alt="HScale Widget">
<div class="figure">Figure: HScale Widget</div>
<br>

<h2>ToggleButton</h2>

<p>
<b class="keyword">ToggleButton</b> is a button that has two states. Pressed and not pressed. 
You toggle between these two states by clicking on it. There are situations where 
this functionality fits well. 
</p>

<div class="codehead">togglebuttons.py</div>
<pre class="code">
#!/usr/bin/python

# ZetCode PyGTK tutorial 
#
# This example demonstrates the ToggleButton widget
#
# author: jan bodnar
# website: zetcode.com 
# last edited: February 2009

import gtk

class PyApp(gtk.Window):
    def __init__(self):
        super(PyApp, self).__init__()

        self.color = [0, 0, 0]
        
        self.set_title("ToggleButtons")
        self.resize(350, 240)
        self.set_position(gtk.WIN_POS_CENTER)
        self.connect("destroy", gtk.main_quit)

        red = gtk.ToggleButton("Red")
        red.set_size_request(80, 35)
        red.connect("clicked", self.onred)
        green = gtk.ToggleButton("Green")
        green.set_size_request(80, 35)
        green.connect("clicked", self.ongreen)
        blue = gtk.ToggleButton("Blue")
        blue.set_size_request(80, 35)
        blue.connect("clicked", self.onblue)

        self.darea = gtk.DrawingArea()
        self.darea.set_size_request(150, 150)
        self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black"))

        fixed = gtk.Fixed()
        fixed.put(red, 30, 30)
        fixed.put(green, 30, 80)
        fixed.put(blue, 30, 130)
        fixed.put(self.darea, 150, 30)

        self.add(fixed)

        self.show_all()

    def onred(self, widget):
        if widget.get_active():
            self.color[0] = 65535
        else: self.color[0] = 0

        self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(self.color[0], 
            self.color[1], self.color[2]))

    def ongreen(self, widget):
        if (widget.get_active()):
            self.color[1] = 65535
        else: self.color[1] = 0

        self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(self.color[0],
            self.color[1], self.color[2]))

    def onblue(self, widget):
        if (widget.get_active()):
            self.color[2] = 65535
        else: self.color[2] = 0

        self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(self.color[0], 
            self.color[1], self.color[2]))


PyApp()
gtk.main()
</pre>

<p>
In our example, we show three toggle buttons and a <b class="keyword">DrawingArea</b>. 
We set the background color of the area to black. The togglebuttons will toggle the red, 
green and blue parts of the color value. The background color will depend on which
togglebuttons we have pressed. 
</p>

<pre class="explanation">
 self.color = [0, 0, 0]
</pre>

<p>
This is the color value that is going to be updated with the toggle buttons. 
</p>

<pre class="explanation">
 red = gtk.ToggleButton("Red")
 red.set_size_request(80, 35)
 red.connect("clicked", self.onred)
</pre>

<p>
The <b class="keyword">ToggleButton</b> widget is created. We set it's size
to 80x35 pixels. Each of the toggle buttons has it's own handler method. 
</p>

<pre class="explanation">
 self.darea = gtk.DrawingArea()
 self.darea.set_size_request(150, 150)
 self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("black"))
</pre>

<p>
The <b class="keyword">DrawingArea</b> widget is the widget, that
displays the color, mixed by the toggle buttons. At start, it shows
black color. 
</p>


<pre class="explanation">
 if widget.get_active():
     self.color[0] = 65535
 else: self.color[0] = 0
</pre>

<p>
If the toggle button is pressed, we change the R, G or B part
of the color accordingly.
</p>

<pre class="explanation">
 self.darea.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(self.color[0], 
            self.color[1], self.color[2]))
</pre>

<p>
We update the color of the <b class="keyword">DrawingArea</b> widget. 
</p>


<br>
<img src="/img/gui/pygtk/togglebuttons.png" alt="ToggleButton widget">
<div class="figure">Figure: ToggleButton widget</div>
<br>


<h2>Calendar</h2>

<p>
Our final widget is the <b class="keyword">Calendar</b> widget. It is used to 
work with dates.
</p>

<div class="codehead">calendar.py</div>
<pre class="code">
#!/usr/bin/python

# ZetCode PyGTK tutorial 
#
# This example demonstrates the Calendar widget
#
# author: jan bodnar
# website: zetcode.com 
# last edited: February 2009


import gtk

class PyApp(gtk.Window):

    def __init__(self):
        super(PyApp, self).__init__()

        self.set_title("Calendar")
        self.set_size_request(300, 270)
        self.set_position(gtk.WIN_POS_CENTER)
        self.set_border_width(2)

        self.label = gtk.Label("...")

        calendar = gtk.Calendar() 
        calendar.connect("day_selected", self.on_day_selected)

        fix = gtk.Fixed()
        fix.put(calendar, 20, 20)
        fix.put(self.label, 40, 230)

        self.add(fix)

        self.connect("destroy", gtk.main_quit)
        self.show_all()
        
    def on_day_selected(self, widget):
        (year, month, day) = widget.get_date()
        self.label.set_label(str(month) + "/" + str(day) + "/" + str(year))
    
        

PyApp()
gtk.main()
</pre>

<p>
We have the <b class="keyword">Calendar</b> widget and a <b class="keyword">Label</b>.
The selected day from the calendar is shown in the label. 
</p>

<pre class="explanation">
 calendar = gtk.Calendar() 
</pre>

<p>
<b class="keyword">Calendar</b> widget is created. 
</p>

<pre class="explanation">
 (year, month, day) = widget.get_date()
 self.label.set_label(str(month) + "/" + str(day) + "/" + str(year))
</pre>

<p>
In the <b class="keyword">on_day_selected()</b> method we retrieve the
currently selected date, and update the label.
</p>


<br>
<img src="/img/gui/pygtk/calendar.png" alt="Calendar">
<div class="figure">Figure: Calendar</div>

<hr class="btm">

<p>
In this chapter of the PyGTK tutorial, we finished talking about the PyGTK widgets. 
</p>


<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified February 7, 2009  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

